#ifndef __SHADER_H__
#define __SHADER_H__
#include <vector>
#include <memory>
#include "light.h"
#include "texture.h"
#include "vec4.h"
#include "vec3.h"
#include "vec2.h"
#include "mat4.h"
#include "log.h"

struct Vertex {
    Vec4f position;
    Vec4f normal;
    TexCoord texCoord;
};

class Shader {
public:
    virtual void VertexShader(Vertex& vert1, Vertex& vert2, Vertex& vert3) = 0;
    virtual Color4u8 FragmentShader(float alpha, float beta, float gamma) = 0;
    virtual ~Shader() = default;
};

class DoNothingShader final : public Shader {
public:
    DoNothingShader() = default;
    DoNothingShader(Mat4x4&& model, Mat4x4&& view, Mat4x4&& proj)
        : mModel(std::move(model)), mView(std::move(view)), mProj(std::move(proj)) {}
    
    Color4u8 color{255, 89, 116, 54};

    void VertexShader(Vertex& vert1, Vertex& vert2, Vertex& vert3) override;
    Color4u8 FragmentShader(float alpha, float beta, float gamma) override;
private:
    Mat4x4 mProj;
    Mat4x4 mView;
    Mat4x4 mModel;
};

class GouraudShader final : public Shader {
public:

private:

};

class PhongShader final : public Shader {
public:
    PhongShader(Mat4x4&& model, Mat4x4&& view, Mat4x4&& proj, const Vec3f& viewPos, 
                const Texture& texture, const std::vector<std::shared_ptr<Light>>& lights)
        : mModel(std::move(model)), mView(std::move(view)), mProj(std::move(proj)), mViewPos(viewPos), 
          mTriPos{}, mTriNormal{}, mTriTexCoord{}, mLights(lights), mTexture(texture) {}

    void VertexShader(Vertex& vert1, Vertex& vert2, Vertex& vert3) override;
    Color4u8 FragmentShader(float alpha, float beta, float gamma) override;
private:
    Mat4x4 mModel, mView, mProj;
    const std::vector<std::shared_ptr<Light>>& mLights;
    const Texture& mTexture;

    Vec3f mViewPos;

    Vec3f mTriPos[3];
    Vec3f mTriNormal[3];
    TexCoord mTriTexCoord[3];
};

#endif
